package com.example.k8s.hello.boot.oss.template;

import com.example.k8s.hello.boot.oss.ObjectStat;
import com.example.k8s.hello.boot.oss.conf.OssProperties;
import com.example.k8s.hello.common.exception.ApiExEnum;
import com.example.k8s.hello.common.exception.BizException;
import lombok.RequiredArgsConstructor;
import org.springframework.util.MimeType;
import software.amazon.awssdk.core.ResponseInputStream;
import software.amazon.awssdk.core.internal.util.Mimetype;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.*;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Path;
import java.util.Date;
import java.util.List;

@RequiredArgsConstructor
public class S3Template implements OssTemplate{

    private final S3Client client;
    private final OssProperties properties;
    @Override
    public boolean bucketExists(String bucket) {
        try {
            // bucketName不存在则新增，注意云服务器厂商的bucket是全局唯一的
            client.headBucket(r -> r.bucket(bucket));
            return true;
        } catch (S3Exception e) {
            return false;
        }
    }

    @Override
    public void createBucket(String bucket) {
        if (!bucketExists(bucket)) {
            // 不同厂商的acl策略设置不一样，最好提前建好bucket
            client.createBucket(r ->r.bucket(bucket));
        }
    }

    @Override
    public void deleteBucket(String bucket) {
        client.deleteBucket(r -> r.bucket(bucket));
    }

    @Override
    public InputStream getObject(String name, String bucket) {
        try {
            return client.getObject(r -> r.bucket(bucket).key(name));
        } catch (NoSuchBucketException e) {
            throw new BizException(ApiExEnum.A0100.name(), "oss文件组" + bucket + "不存在", e);
        } catch (NoSuchKeyException e) {
            throw new BizException(ApiExEnum.A0101.name(), "oss文件" + name + "不存在", e);
        }

    }

    @Override
    public ObjectStat getObjectStat(String name, String bucket) {
        GetObjectResponse response = client.getObject(r -> r.bucket(bucket).key(name)).response();

        return new ObjectStat()
                .setEtag(response.eTag())
                .setLength(response.contentLength())
                .setName(name)
                .setLastModified(Date.from(response.lastModified()))
                .setContentType(response.contentType())
                .setBucketName(bucket);

    }

    @Override
    public void putObject(InputStream is, String name, String bucket) {
        long available = 0;
        try {
            available = is.available();
        } catch (IOException e) {
            throw new RuntimeException("oss putObject 出错", e);
        }

        client.putObject(b -> b.bucket(bucket).key(name).contentType(Mimetype.getInstance().getMimetype(Path.of(name)))
                , RequestBody.fromInputStream(is, available));
    }

    @Override
    public void deleteObject(String name, String bucket) {
        client.deleteObject(r -> r.bucket(bucket).key(name));
    }

    @Override
    public List<String> listBuckets() {
        return client.listBuckets().buckets().stream().map(Bucket::name).toList();
    }

    @Override
    public List<String> listObjects(String bucket) {
        return client.listObjects(r -> r.bucket(bucket).bucket(bucket)).contents().stream().map(S3Object::key).toList();
    }

    @Override
    public void deleteObjects(String bucket, List<String> objects) {
        List<ObjectIdentifier> list = objects.stream().map(object -> ObjectIdentifier.builder().key(object).build()).toList();

        Delete delete = Delete.builder().objects(list).build();

        client.deleteObjects(r -> r.bucket(bucket).delete(delete));
    }
}
